-
Notifications
You must be signed in to change notification settings - Fork 182
Move pathfinder
to cuda-python top level
#723
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…HOUT trying to make anything work.
… trying to make anything work.
…make anything work.
…ns.abc.Sequence (Python 3.9+)
…init__.py (to make the dynamic version work).
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
path_finder
to cuda-python top levelpathfinder
to cuda-python top level
def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: | ||
"""Load a NVIDIA dynamic library by name. | ||
|
||
Args: | ||
libname: The name of the library to load (e.g. "cudart", "nvvm", etc.) | ||
|
||
Returns: | ||
A LoadedDL object containing the library handle and path | ||
|
||
Raises: | ||
RuntimeError: If the library cannot be found or loaded | ||
""" | ||
return _load_nvidia_dynamic_lib.load_lib(libname) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could define this wrapper function in the _dynamic_libs
module and just import it here. This way your __init__.py
here wouldn't have a ton of function definitions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is meant to be the public API in one view.
This way your
__init__.py
here wouldn't have a ton of function definitions.
I understood exactly that was your goal: a flat list of available APIs.
Note that I moved the docstring here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is meant to be the public API in one view.
Indeed, everything we define (or import) here that is not prefixed with _
constitutes the public API of the module cuda.path_finder
. My above suggestion is just that we import load_nvidia_dynamic_lib
rather than define it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would make the public API far less obvious. E.g. to see the docstring, they'd need to open a private file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's true. They could still do:
from cuda.path_finder import load_nvidia_dynamic_lib
help(load_nvidia_dynamic_lib)
Same as they would do now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'll only work interactively.
What I have now can be inspected in obvious ways directly in the sources, e.g. when looking at the sources on github. I can send URLs pointing to specific APIs in this init.py file.
Each function here will just be:
def function(...) -> ...:
"""docstring""
return call_into_private_code(...)
That's exactly the public API, with a one-line call that's easy to ignore.
What's the point of hiding that away, especially hiding away the docstring and the type hints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'll only work interactively.
The docstrings and type hints would also get picked up:
- Sphinx (which we use to generate API docs
-pydoc
- the developers' IDEs/lsp
Those are primarily the ways consumers of a package interact with docstrings or type hints, rather than looking directly at the source.
What's the point of hiding that away, especially hiding away the docstring and the type hints?
It tightens the scope of __init__.py
, whose job is:
- to include any initialization code for the module
- to import stuff from submodules that the module wants to expose
- to define
__all__
for the module if needed
As examples, we can look at the __init__.py
from some other popular libraries:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It tightens the scope of init.py, whose job is
The most important job: Show the public API
You didn't answer why you want to hide that away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm advocating for keeping function and type definitions outside of __init__.py
. I don't think that "hides" anything from the user as we still import them here.
The main reason I'm advocating for that is because __init__.py
typically only defines functions and types needed for module initialization, and imports anything else. I think the examples I linked to above are a good demonstration of that.
Defining functions and types beyond that serves to clutter __init__.py
.
I would argue it makes the code base less navigable than more for people looking at the source. Do I expect the function load_nvidia_dynamic_libs
to be defined in a file called _dynamic_libs.py
, or a file called __init__.py
?
If this all seems nitpicky, I apologize. While I do have a strong opinion here, I don't mind at all if another reviewer (or you, as the author of this PR) made the final call about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cuda.core's __init__.py
is a good example for what Ashwin suggested. As a developer who occasionally peeks into someone else's __init__.py
, I certainly get confused why we are defining things in there directly, as opposed to properly organizing them in respective public/private modules, and just import them. What's imported are considered public APIs (including types). Does it make sense?
I'm a bit lost, to be honest, and I’d appreciate some clarification so I can move this forward in the direction you want. The goals that seemed most important to me originally (from a Slack post last Wednesday) were:
After Ashwin’s comment on Slack, I interpreted the request as: prioritize a flat public API, even if that means giving up on some of that isolation — especially when type hints are involved. Then Leo wrote:
That seems more aligned with what I had before the last commit (e.g., a file like I’m happy to implement what you both want here — I just need a bit more clarity. If we go back to what I proposed last week: from cuda.pathfinder import nvidia_dynamic_libs, nvidia_static_libs, nvidia_headers
nvidia_dynamic_libs.load("nvrtc")
nvidia_static_libs.find("cudart")
nvidia_headers.find_file("cuda.h") The file structure was:
I thought that structure balanced modularity and clarity, and users could still import just what they needed. But it sounds like we might instead prefer: from cuda.pathfinder import load_nvidia_dynamic_lib, find_nvidia_static_lib, find_nvidia_header_file That keeps the API flat, but does give up on the isolation goal unless we resort to function-local imports or other workarounds. Could you please help me understand: What would be the preferred file/module structure to go along with the flat API? Should I keep separate modules like |
At this point we need to follow up offline. I think there is a gap that we unfortunately did not really cover during the weekly meeting. I suggest we don't cancel the dev meeting tomorrow and use the time to finalize it. This PR also needs at least @kkraus14's approval for the change of license. |
This looks good to me, sans the one comment above about the visibility of things in the |
/ok to test |
I just added one more commit to this PR, just one extra line: eedf658 After reading up on publishing to PyPI, I'm guessing this is all that's needed on this end to publish |
I was thinking of making a release right after this is merged.
This whole file is already deprecated per the README. I guess we could just add more underscores, would that be acceptable?
Get Outlook for iOS<https://aka.ms/o0ukef>
________________________________
From: Keith Kraus ***@***.***>
Sent: Friday, July 11, 2025 9:24:22 PM
To: NVIDIA/cuda-python ***@***.***>
Cc: Ralf Grosse Kunstleve ***@***.***>; Mention ***@***.***>
Subject: Re: [NVIDIA/cuda-python] Move `pathfinder` to cuda-python top level (PR #723)
@kkraus14 commented on this pull request.
________________________________
In cuda_bindings/cuda/bindings/path_finder.py<#723 (comment)>:
__all__ = [
"_load_nvidia_dynamic_library",
"_SUPPORTED_LIBNAMES",
]
I do not think it's fine. We're following strict semver here, which means if you can publicly access something via cuda.bindings.path_finder that doesn't begin with an underscore that it is part of our API and we will not break it in bumping minor versions.
If this is only a temporary stopgap that we don't intend to survive until a release then that is fine.
—
Reply to this email directly, view it on GitHub<#723 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AAFUZACZPGCREHK5PLRHQYT3ICEXNAVCNFSM6AAAAAB77RWJV2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTAMJSGYZTKMRRG4>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
…backward_compatibility.py, to fully sanitize path_finder.py
/ok to test |
cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py
Show resolved
Hide resolved
- Move mypy configuration from cuda_pathfinder/mypy.ini to [tool.mypy] section in pyproject.toml - Delete cuda_pathfinder/mypy.ini file - Update .pre-commit-config.yaml to point to pyproject.toml for mypy configuration - Maintain identical functionality with consolidated config Addresses review comment about preferring pyproject.toml over separate ini files.
…ersion release." Also fix pathfinder → path_finder oversights.
…hat this wasn't removed before).
I'm not rerunning the CI:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -286,6 +292,11 @@ jobs: | |||
- name: Set up compute-sanitizer | |||
run: setup-sanitizer | |||
|
|||
- name: Run cuda.pathfinder tests with see_what_works |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Later the pathfinder will need to check the driver version, so the status quo is fine.
if dll.startswith("nvrtc-builtins"): | ||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For NVRTC wheel to work on Windows, this DLL is needed, e.g.
https://github.com/NVIDIA/nvmath-python/blob/e082fedb46a57072e63d3b8f0aae3b451eeddcbb/nvmath/_utils.py#L139
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I just forget what "suppressed DLLs" means...
pointer_size_bits = struct.calcsize("P") * 8 | ||
if pointer_size_bits != 64: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI usually we can check this with sys.maxsize > 2**32
:
https://docs.python.org/3/library/platform.html#platform.architecture
btw @rwgk could you create an issue to track the need to add docs for pathfinder? We need a Sphinx-rendered docs. |
/ok to test |
Just to explain, that's my preferred work style, too, but two things led to the current situation:
|
|
Description
Closes #719, #708
Note: The name is changed from
path_finder
topathfinder
. The word "pathfinder" is very common, and it avoids underscore/dash confusion between directory names and package names.Move
cuda.bindings.path_finder
→cuda.pathfinder
, with backward compatibility:cuda.bindings.path_finder
forwards tocuda.pathfinder
.LoadedDL._handle
private (underscore prefix). It is now a platform-agnostic unsigned integer.Make
cuda-bindings
dependent oncuda-pathfinder
, with a temporary backward compatibility layer. —cuda.bindings.pathfinder
is slated to be removed after the nextcuda-bindings
release.Remove 32-bit DLL names from
SUPPORTED_WINDOWS_DLLS
and add runtime guard incuda.pathfinder.load_nvidia_dynamic_lib()
: "requires 64-bit Python".Add specific
DynamicLibNotFoundError
exception type to public API (this wasRuntimeError
before; now inherits fromRuntimeError
).Run
mypy-pathfinder
frompre-commit
(after systematicmypy
cleanup of library code).Adjust GitHub Actions jobs to the move.
Add
nvidia_wheels_cu12
to[project.optional-dependencies]
incuda_pathfinder/pyproject.toml
and ensure all libs are loaded successfully. Treat all NVIDIA libs as "supported".Mark
cuda.pathfinder
as version 1.0.0